跳到主要内容

Golang 读取配置文件之 viper 包

作者spf13有两个明星项目—cobra & viper (眼睛蛇与蝮蛇)

image9a605b9eae251c70.png

Cobra 已经学习了,这里主要介绍下 viper 咋用

viper 用来读取初始的配置文件

设置默认值

一个好的项目需要在引入配置文件之前使用一些默认值,可以通过以下方式构建

viper.SetDefault("ContentDir", "content")
viper.SetDefault("LayoutDir", "layouts")
viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})

读取配置文件

支持的配置文件格式:JSON, TOML, YAML, HCL, envfile and Java properties config files Viper 可以搜索多个路径,但单个 Viper 实例只支持单个配置文件。

具体的使用规则如下:

// 加载配置文件之前,设置一些配置
viper.SetConfigName("config") // 配置文件名称
viper.SetConfigType("yaml") // 配置文件的拓展名

viper.AddConfigPath("/etc/appname/") // 配置文件的路径
viper.AddConfigPath("$HOME/.appname") // 可设置多个搜索路径
viper.AddConfigPath(".") // 可选在当前工作空间中查找

err := viper.ReadInConfig() // 找到并加载配置文件
if err != nil { // 处理错误
panic(fmt.Errorf("Fatal error config file: %w \n", err))
}

运行时读取配置文件

确保在调用 WatchConfig() 之前添加了所有的 configPaths

viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
})
viper.WatchConfig()

从IO流中读取配置文件

viper.SetConfigType("yaml") // or viper.SetConfigType("YAML")

// any approach to require this configuration into your program.
var yamlExample = []byte(`
Hacker: true
name: steve
hobbies:
- skateboarding
- snowboarding
- go
clothing:
jacket: leather
trousers: denim
age: 35
eyes : brown
beard: true
`)

viper.ReadConfig(bytes.NewBuffer(yamlExample))

viper.Get("name") // this would be "steve"

Get 值

Get(key string) : interface{}
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetIntSlice(key string) : []int
GetString(key string) : string
GetStringMap(key string) : map[string]interface{}
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]interface{}

如果没有找到,每个Get函数将返回一个零值。为了检查给定的键是否存在,提供了 IsSet() 方法。

获取多重嵌套的Key、数组:

// {
// "host": {
// "address": "localhost",
// "ports": [
// 5799,
// 6029
// ]
// },
// "datastore": {
// "metric": {
// "host": "127.0.0.1",
// "port": 3099
// },
// "warehouse": {
// "host": "198.0.0.1",
// "port": 2112
// }
// }
// }

GetInt("host.ports.1") // returns 6029

注意: 如果有与上述方法中 . 取健相同,那么就使用该健(下面第一行)

// {
// "datastore.metric.host": "0.0.0.0",
// "host": {
// "address": "localhost",
// "port": 5799
// },
// "datastore": {
// "metric": {
// "host": "127.0.0.1",
// "port": 3099
// },
// "warehouse": {
// "host": "198.0.0.1",
// "port": 2112
// }
// }
// }

GetString("datastore.metric.host") // returns "0.0.0.0"

重设值与覆盖、键使用别名

viper.Set("Verbose", true)
viper.Set("LogFile", LogFile)


// 注册
viper.RegisterAlias("loud", "Verbose")

viper.Set("verbose", true) // same result as next line
viper.Set("loud", true) // same result as prior line

viper.GetBool("loud") // true
viper.GetBool("verbose") // true

覆写配置文件

// 如果存在,则将当前 viper 配置写入预定义路径。如果没有预定义的路径,则返回错误。将覆盖当前配置文件,如果它存在。
viper.WriteConfig() // 将viper中的配置保存到'viper.AddConfigPath()' and 'viper.SetConfigName'预定义的配置文件中

// 将当前的 viper 配置写入预定义的路径。如果没有预定义的路径,则返回错误。将不会覆盖当前配置文件,如果它存在。
viper.SafeWriteConfig()

// 将当前 viper 配置写入给定的文件路径。将覆盖给定的文件,如果它存在。
viper.WriteConfigAs("/path/to/my/.config")


viper.SafeWriteConfigAs("/path/to/my/.config") // will error since it has already been written

// 将当前的 viper 配置写入给定的文件路径。如果给定的文件存在,则不会覆盖该文件。
viper.SafeWriteConfigAs("/path/to/my/.other_config")

读取配置文件示例

package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var (
// Used for flags.
cfgFile string
userLicense string

rootCmd = &cobra.Command{
Use: "cobra",
Short: "A generator for Cobra based Applications",
Long: `Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}
)

// Execute executes the root command.
func Execute() error {
return rootCmd.Execute()
}

func init() {
// 初始化操作
cobra.OnInitialize(initConfig)

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")

viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")

rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(initCmd)
}

// 一般在这里读取配置文件或者环境变量
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// 搜索在 home 目录下后缀名为 .cobra 的配置文件(可以自定义)
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".cobra")
}

// read in environment variables that match
viper.AutomaticEnv()

if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}

References

go项目cli与配置文件:cobra与viper项目